<!DOCTYPE html>
<html>
<head>
    <title>PlayCanvas Physics</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
    <link rel="icon" type="image/png" href="../playcanvas-favicon.png" />
    <script src="../../build/output/playcanvas.js"></script>
    <script src="../wasm-loader.js"></script>
    <style>
        body { 
            margin: 0;
            overflow-y: hidden;
        }
    </style>
</head>

<body>
    <!-- The canvas element -->
    <canvas id="application-canvas"></canvas>

    <!-- The script -->
    <script>
    if (wasmSupported()) {
        loadWasmModuleAsync('Ammo', '../lib/ammo/ammo.wasm.js', '../lib/ammo/ammo.wasm.wasm', demo);
    } else {
        loadWasmModuleAsync('Ammo', '../lib/ammo/ammo.js', '', demo);
    }

    function demo() {
        // ***********    Initialize application   *******************
        var canvas = document.getElementById("application-canvas");

        // Create the application and start the update loop
        var app = new pc.Application(canvas);
        app.start();

        // Set the canvas to fill the window and automatically change resolution to be the same as the canvas size
        app.setCanvasFillMode(pc.FILLMODE_FILL_WINDOW);
        app.setCanvasResolution(pc.RESOLUTION_AUTO);

        window.addEventListener("resize", function () {
            app.resizeCanvas(canvas.width, canvas.height);
        });

        app.scene.ambientLight = new pc.Color(0.2, 0.2, 0.2);

        // Set the gravity for our rigid bodies
        app.systems.rigidbody.gravity.set(0, -9.81, 0);

        function createMaterial (color) {
            var material = new pc.StandardMaterial();
            material.diffuse = color;
            // we need to call material.update when we change its properties
            material.update()
            return material;
        }

        // create a few materials for our objects
        var white = createMaterial(new pc.Color(1, 1, 1));
        var red = createMaterial(new pc.Color(1, 0, 0));
        var green = createMaterial(new pc.Color(0, 1, 0));
        var blue = createMaterial(new pc.Color(0, 0, 1));
        var yellow = createMaterial(new pc.Color(1, 1, 0));

        // ***********    Create our floor   *******************

        var floor = new pc.Entity();
        floor.addComponent("model", {
            type: "box"
        });

        // make the floor white
        floor.model.material = white;

        // scale it
        floor.setLocalScale(10, 1, 10);

        // add a rigidbody component so that other objects collide with it
        floor.addComponent("rigidbody", {
            type: "static",
            restitution: 0.5
        });

        // add a collision component
        floor.addComponent("collision", {
            type: "box",
            halfExtents: new pc.Vec3(5, 0.5, 5)
        });

        // add the floor to the hierarchy
        app.root.addChild(floor);

        // ***********    Create lights   *******************

        // make our scene prettier by adding a directional light
        var light = new pc.Entity();
        light.addComponent("light", {
            type: "directional",
            color: new pc.Color(1, 1, 1),
            castShadows: true,
            shadowBias: 0.2,
            shadowDistance: 16,
            normalOffsetBias: 0.05,
            shadowResolution: 2048
        });

        // set the direction for our light
        light.setLocalEulerAngles(45, 30, 0);

        // Add the light to the hierarchy
        app.root.addChild(light);

        // ***********    Create camera    *******************

        // Create an Entity with a camera component
        var camera = new pc.Entity();
        camera.addComponent("camera", {
            clearColor: new pc.Color(0.5, 0.5, 0.8),
            farClip: 50
        });

        // add the camera to the hierarchy
        app.root.addChild(camera);

        // Move the camera a little further away
        camera.translate(0, 10, 15);
        camera.lookAt(0, 0, 0);

        // ***********    Create templates    *******************

        // Create a template for a falling box
        // It will have a model component of type 'box'...
        var boxTemplate = new pc.Entity();
        boxTemplate.addComponent("model", {
            type: "box",
            castShadows: true
        });

         // ...a rigidbody component of type 'dynamic' so that it is simulated
        // by the physics engine...
        boxTemplate.addComponent("rigidbody", {
            type: "dynamic",
            mass: 50,
            restitution: 0.5
        });

        // ... and a collision component of type 'box'
        boxTemplate.addComponent("collision", {
            type: "box",
            halfExtents: new pc.Vec3(0.5, 0.5, 0.5)
        });

        // make the box red
        boxTemplate.model.material = red;

        // Create other shapes too for variety...

        // A sphere...
        var sphereTemplate = new pc.Entity();
        sphereTemplate.addComponent("model", {
            type: "sphere",
            castShadows: true
        });

        sphereTemplate.addComponent("rigidbody", {
            type: "dynamic",
            mass: 50,
            restitution: 0.5
        });

        sphereTemplate.addComponent("collision", {
            type: "sphere",
            radius: 0.5
        });


        // make the sphere green
        sphereTemplate.model.material = green;

        // A capsule...
        var capsuleTemplate = new pc.Entity();
        capsuleTemplate.addComponent("model", {
            type: "capsule",
            castShadows: true
        });

        capsuleTemplate.addComponent("rigidbody", {
            type: "dynamic",
            mass: 50,
            restitution: 0.5
        });

        capsuleTemplate.addComponent("collision", {
            type: "capsule",
            radius: 0.5,
            height: 2
        });


        // make the capsule blue
        capsuleTemplate.model.material = blue;

        // A cylinder...
        var cylinderTemplate = new pc.Entity();
        cylinderTemplate.addComponent("model", {
            type: "cylinder",
            castShadows: true
        });

        cylinderTemplate.addComponent("rigidbody", {
            type: "dynamic",
            mass: 50,
            restitution: 0.5
        });

        cylinderTemplate.addComponent("collision", {
            type: "cylinder",
            radius: 0.5,
            height: 1
        });


        // make the cylinder yellow
        cylinderTemplate.model.material = yellow;

        // add all the templates to an array so that
        // we can randomly spawn them
        var templates = [boxTemplate, sphereTemplate, capsuleTemplate, cylinderTemplate];

        // disable the templates because we don't want them to be visible
        // we'll just use them to clone other Entities
        templates.forEach(function (template) {
            template.enabled = false;
        })

        // ***********    Update Function   *******************

        // initialize variables for our update function
        var timer = 0;
        var count = 40;

        // Set an update function on the application's update event
        app.on("update", function (dt) {
            // create a falling box every 0.2 seconds
            if (count > 0) {
                timer -= dt;
                if (timer <= 0) {
                    count--;
                    timer = 0.2;

                    // Clone a random template and position it above the floor
                    var template = templates[Math.floor(pc.math.random(0, templates.length))];
                    var clone = template.clone();
                    // enable the clone because the template is disabled
                    clone.enabled = true;

                    app.root.addChild(clone);

                    clone.rigidbody.teleport(pc.math.random(-1, 1), 10, pc.math.random(-1, 1));
                }
            }
        });
    }
    </script>
</body>
</html>
